package work.ib.apt.perf.complex;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import utils.MyUtils;

public class GetReviewList {

	//	private static final String url = "http://localhost:8000/services/review/v1/getReviewDetails";
	//	private static final String url = "http://dev-aptratings-services1.internetbrands.com:8080/services/review/v2/getReviews";
	private final String url = "http://stg-services.apartmentratings.com/services/review/v2/getReviews";


	private final Integer threadCount = 500;
	private final int threadsPerSecond = 5;
	protected int parallelThreads = 50;


	private static long[] complexIdStg = new long[] {
		360695955398661l,
		925682165594520l,
		850350900032304l,
		810263890048038l,
		9414299799342891l,
		714633759292867l,
		866704327690017l,
		305854155033129l,
		714964556792646l,
		303756544480222l,
		954247120033067l,
		317290364146260l,
		512476221978703l,
		732721717108857l,
		847524962960193l,
		210828319678209l,
		704542333228226l,
		310649736890045l,
		847397846860008l,
		817485477676180l,
		972315970075067l,
		310827028290292l,
		615220400037167l,
		909803222391739l,
		972459180075057l,
		4057212191731328l,
		407321770032746l,
		410789359721090l,
		770476551530097l,
		781321211402148l,
		4073971800347473054l,
		703823350022304l,
		623492050085027l,
		909599931891773l,
		703435190020171l,
		770484888730038l,
		703998724022302l,
		503537306697132l,
		972335580075034l,
		469892010075287l,
		248477575548152l,
		817731919176109l,
		757422540123451l,
		410356506221117l,
		973347771107857l,
		714536390192646l,
		512836000978753l,
		727360807733706l,
		866457771892056l,
		512257400078729l,
	};


//	private static long[] complexIdDev = new long[] {
//		9199332346275147327l,
//		414778151553226l,
//		410247333321227l,
//		9199332346275144038l,
//		520572000685743l,
//		817451350576112l,
//		281208277977477l,
//		570343565018508l,
//		732246462708873l,
//		510887818594545l,
//		215343450018976l,
//		805942073093534l,
//		817540404076021l,
//		617364527702136l,
//		805263040491354l,
//		703968444022030l,
//		9199332346275146679l,
//		502227983740601l,
//		281440716277066l,
//		9199332346275151608l,
//		903561610175703l,
//		866742034947150l,
//		610775010519607l,
//		503848627997007l,
//		703413540022202l,
//		909245033892530l,
//		440842912144129l,
//		4042969330300212087l,
//		719598655080918l,
//		951369107892507l,
//		909628898191709l,
//		9199332346275148378l,
//		301948063620878l,
//		877266572332817l,
//		928714103086004l,
//		704548115428269l,
//		915692270179605l,
//		410821788821204l,
//		813875660933603l,
//		215682200019040l,
//		714842062992647l,
//		864292184029615l,
//		704588300028273l,
//		706320090931904l,
//		703751699022304l,
//		254755726776706l,
//		803732088029212l,
//		773477770060657l,
//		301423313120746l,
//		202244772420008l,
//		9199332346275150446l,
//		310568940090045l,
//		817261166376120l,
//		20743l,
//		410488903321206l,
//		513523766645056l,
//		9199332346275152162l,
//		2888829451334873886l,
//		9199332346275143017l,
//		213406800090015l,
//		9199332346275151583l,
//		9199332346275143004l,
//		9199332346275151257l,
//		715386776754016l,
//		770888590030041l,
//		21496565657520401l,
//		770434614430080l,
//		901365831838118l,
//		9199332346275143280l,
//		866510308498444l,
//		513234065945065l,
//		877262845630326l,
//		703690216122191l,
//		602843149985308l,
//		713665472077054l,
//		805306996693065l,
//		623492903585087l,
//		7574840195237031l,
//		314434698863043l,
//		281586736077069l,
//		9199332346275148517l,
//		512288340078749l,
//		205822017035216l,
//		407805022232746l,
//		617288833002121l,
//		703813818322312l,
//		410730192221045l,
//		925846888294566l,
//		813925841133626l,
//		9199332346275145178l,
//		800901862519382l,
//		813249486033634l,
//		623931387885302l,
//		949551680092604l,
//		757988028823608l,
//		256837156635806l,
//		757595537323606l,
//		9199332346275153539l,
//		901365243038118l,
//		904642728832256l,
//
//	};

	public static void main(String[] args) {
		try {
			new GetReviewList().runTest();
		} catch (Exception e) {
			e.printStackTrace(System.out);
		}
	}


	public void runTest() {
		System.out.println(new Date());
		try {
			ThreadPoolExecutor executor = new ThreadPoolExecutor(getParallelThreads(),getParallelThreads(),300L,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
			int totalThreads = 0;
			while (totalThreads < getThreadCount()) {
				for (int i = 0; i < getThreadsPerSecond(); i++) {
					totalThreads++;
					executor.execute(new MyRunnable(totalThreads,getParameters(),executor,getURL()));
				}
				Thread.sleep(1000);
			}

			while (!executor.awaitTermination(300L, TimeUnit.SECONDS)) {}

		} catch (Exception e) {
			e.printStackTrace(System.out);
		}
		System.out.println(new Date());
	}

	public Map<String, Object> getParameters() {
		long[] dataArray = complexIdStg;
		long complexId = dataArray[new Random().nextInt(dataArray.length)];
		Map<String,Object> params = new HashMap<String,Object>();

		params.put("complexId", complexId);
		params.put("page", 0);
		params.put("orderBy", 0);
		params.put("filterWords", true);

		String loadImages = "false";
		int pageSize = 999;

		params.put("loadImages", loadImages);
		params.put("pageSize", pageSize);
		params.put("format", "json");

		return params;
	}


	public String getURL() {
		return url;
	}


	public int getThreadCount() {
		return threadCount;
	}


	public int getThreadsPerSecond() {
		return threadsPerSecond;
	}


	public int getParallelThreads() {
		return parallelThreads;
	}

	static class MyRunnable implements Runnable {

		private Map<String,Object> params;
		private final ThreadPoolExecutor executor;
		private final String url;
		private final int threadNumber;

		public MyRunnable(int threadNumber, Map<String,Object> params, ThreadPoolExecutor executor, String url) {
			this.params = params;
			this.executor = executor;
			this.url = url;
			this.threadNumber = threadNumber;
		}

		@Override
		public void run() {
			try {
				Thread.sleep(new Random().nextInt(1000)+1);
				String queryString = createQueryString();
				String uri = url + "?" + queryString;
//				System.out.println(uri);
				String response = getResponse(uri);
				System.out.println(threadNumber);
//				if (threadNumber % 100 == 0) {
//					System.out.println(response);
//				}
			} catch (Exception e) {
				e.printStackTrace(System.out);
			} finally {
				System.out.println("Active threads " + executor.getActiveCount());
				// This should probably be synchronized
				if (executor.getActiveCount() == 1 && executor.getQueue().isEmpty()) {
					executor.shutdown();
				}
			}
		}

		// Dirty, I should use try/catch/finally and close connections
		private String getResponse(String uri) throws IOException {
			URL url = new URL(uri);
			URLConnection con = url.openConnection();
			InputStream input = con.getInputStream();
			StringWriter writer = new StringWriter();
			MyUtils.copy(input, writer);
			String body = writer.toString();
			return body;
		}

		private String createQueryString() {
			StringBuilder sb = new StringBuilder();

			for (Entry<String, Object> entry : params.entrySet()) {
				if (sb.length() != 0) {
					sb.append("&");
				}
				try {
					sb.append(entry.getKey()).append("=").append(URLEncoder.encode(String.valueOf(entry.getValue()),"UTF-8"));
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace(System.out);
				}
			}

			return sb.toString();
		}

	}
}
